#ifndef _LINK_H
#define _LINK_H 1

#include "wordsize.h"
#include "elf.h"

#define __ELF_NATIVE_CLASS __WORDSIZE

#define ElfW(type) _ElfW(Elf, __ELF_NATIVE_CLASS, type)
#define _ElfW(e, w, t) _ElfW_1(e, w, _##t)
#define _ElfW_1(e, w, t) e##w##t


typedef ElfW(Half) Elf_Half;
typedef ElfW(Word) Elf_Word;
typedef ElfW(Sword) Elf_Sword;
typedef ElfW(Xword) Elf_Xword;
typedef ElfW(Sxword) Elf_Sxword;
typedef ElfW(Addr) Elf_Addr;
typedef ElfW(Off) Elf_Off;
typedef ElfW(Section) Elf_Section;
typedef ElfW(Versym) Elf_Versym;
typedef ElfW(Ehdr) Elf_Ehdr;
typedef ElfW(Shdr) Elf_Shdr;
typedef ElfW(Chdr) Elf_Chdr;
typedef ElfW(Sym) Elf_Sym;
typedef ElfW(Syminfo) Elf_Syminfo;

#define _ELF_MACRO_DEFINE(suffix, args...) _ELF_MACRO_DEFINE_1(__WORDSIZE, suffix, ##args)
#define _ELF_MACRO_DEFINE_1(wordsize, suffix, args...) _ELF_MACRO_DEFINE_2(wordsize, suffix, ##args)
#define _ELF_MACRO_DEFINE_2(wordsize, suffix, args...) ELF##wordsize##_##suffix(args)

#define ELF_ST_BIND(val) _ELF_MACRO_DEFINE(ST_BIND, val)
#define ELF_ST_TYPE(val) _ELF_MACRO_DEFINE(ST_TYPE, val)
#define ELF_ST_INFO(bind, type) _ELF_MACRO_DEFINE(ST_INFO, bind, type)
#define ELF_ST_VISIBILITY(o) _ELF_MACRO_DEFINE(ST_VISIBILITY, o)

typedef ElfW(Rel) Elf_Rel;
typedef ElfW(Rela) Elf_Rela;

#define ELF_R_SYM(val) _ELF_MACRO_DEFINE(R_SYM, val)
#define ELF_R_TYPE(val) _ELF_MACRO_DEFINE(R_TYPE, val)
#define ELF_R_INFO(sym, type) _ELF_MACRO_DEFINE(R_INFO, sym, type)

typedef ElfW(Phdr) Elf_Phdr;
typedef ElfW(Dyn) Elf_Dyn;
typedef ElfW(Verdef) Elf_Verdef;
typedef ElfW(Verdaux) Elf_Verdaux;
typedef ElfW(Verneed) Elf_Verneed;
typedef ElfW(Vernaux) Elf_Vernaux;
typedef ElfW(auxv_t) Elf_auxv_t;
typedef ElfW(Nhdr) Elf_Nhdr;
typedef ElfW(Move) Elf_Move;

#define ELF_M_SYM(info) _ELF_MACRO_DEFINE(M__SYM, info)
#define ELF_M_SIZE(info) _ELF_MACRO_DEFINE(M_SIZE, info)
#define ELF_M_INFO(sym, size) _ELF_MACRO_DEFINE(M_INFO, sym, size)

#endif //_LINK_H
